package com.qire.common.inject;

import com.qire.antsbinder.utils.TypeUtils;
import com.qire.antsrouter.card.Postcard;
import com.qire.antsrouter.inject.Injector;
import com.qire.antsrouter.utils.ClassUtils;
import com.qire.common.basic.ObjectUtil;
import com.qire.common.support.base.EventController;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;

import androidx.lifecycle.LifecycleOwner;

/**
 * 统一EventController注入器，该注入器目标提供给Activity及Fragment使用，希望在注入时自动完成绑定到 UI（viewDataBinder）上的功能。
 * 但由于Activity和Fragment的viewDataBinder的构建时期不同（生命周期），所以依赖LifecycleOwner来完成，因为A和F都实现了LifecycleOwner接口，
 * 且EventController也受所有者生命周期约束，固构建依赖LifecycleOwner完成。在具体的EventController内完成通过生命周期监听完成绑定。
 */
public class EventControllerInjector implements Injector<Postcard, LifecycleOwner> {

    /**
     * 事件控制器注入行为
     * @param field 注入目标字段
     * @param postcard 跳卡实体
     * @param injectedTarget 注入目标
     */
    @Override
    public void inject(Field field, Postcard postcard, LifecycleOwner injectedTarget) {
        // 如果目标注入对象中存在值，则不做第二次构建注入
        if(ObjectUtil.nonNull(ClassUtils.getFieldValue(field, injectedTarget))) {
            return;
        }

        // todo:希望在后期从框架级别解决这个问题
        //-------------------修改页面导航框架页面Go寻址跳转后，页面注入传值会导致自定义注解器执行2次，顾做上面的修复-------------------------

        // 创建EventController<O extends LifecycleOwner>，废弃原有模板签名EventController<O extends LifecycleOwner,VB ViewDataBinding>
        try {
            // 1.获取注入目标字段类型
            Class<? extends EventController> controllerClass = (Class<? extends EventController>)field.getType();

            // 2.通过注入目标字段类型获取EventController的构造泛型类型数组；
            // 注原本构造函数需要传递viewDataBinder后面取消了，因为注入时可能还未到合适的生命周期，固viewDataBinder的bind放到具体实现中完成
            Type[] parameterTypes = TypeUtils.getSuperclassTypeParameter(controllerClass);
            int typesLength = parameterTypes.length;
            Class<?>[] parameterClassList = new Class[typesLength];
            for(int index = 0; index < typesLength; index++) {
                parameterClassList[index] =  (Class<?>) parameterTypes[index];
            }

            // 3.通过泛型类型数组获对应参数的构造函数
            Constructor<? extends EventController> controllerConstructor = controllerClass.getConstructor(parameterClassList);

            // 4.通过构造器 new 出对应实体
            EventController controller = controllerConstructor.newInstance(injectedTarget);

            // 5.反射注入实体对象到目标字段上
            field.setAccessible(true);
            field.set(injectedTarget,controller);
            field.setAccessible(false);
        } catch (SecurityException | IllegalArgumentException | IllegalAccessException |
                NoSuchMethodException | InstantiationException | InvocationTargetException e) {
            e.printStackTrace();
        }

    }

}